import {
  Observable, of,
  tap,
} from 'rxjs'

// 里面包含路由处理函数
const next = {
  handle() {
    console.log(`pay...`)
    return of('路由处理函数的返回值') // 路由处理函数返回一个可观察对象
  }
}

export class Logger1Interceptor {
  intercept(_, next): Observable<any> {
    console.log('Before1')
    const now = Date.now()
    return next.handle().pipe(
      tap({
        next: val => console.log(`After1... ${Date.now() - now}ms`, val)
      }),
    )
  }
}
export class Logger2Interceptor {
  intercept(_, next): Observable<any> {
    console.log('Before2')
    const now = Date.now()
    return next.handle().pipe(
      tap({
        next: val => console.log(`After2... ${Date.now() - now}ms`, val)
      }),
    )
  }
}

const logging1Interceptor = new Logger1Interceptor()
const logging2Interceptor = new Logger2Interceptor()

// 内部包含了路由处理函数的执行逻辑
const originalHandler = () => next.handle()

// 内部包含 originalHandler 函数的执行逻辑
const logger1Handler = () => logging1Interceptor.intercept(null, { handle: originalHandler })

// 内部包含了 logger1Handler 函数的执行逻辑
const logger2Handler = () => logging2Interceptor.intercept(null, { handle: logger1Handler })


logger2Handler()
  .subscribe(console.log);

/**
 * 定义逻辑
 * 1. 定义一个 originalHandler 函数 里面包含路由处理函数的执行逻辑
 *   1.1 路由处理函数会返回一个可观察对象
 * 2. 定义一个 logger1Handler 函数 里面包含 logging1Interceptor.intercept (第一个拦截器)函数的执行逻辑
 *   2.1 执行 logging1Interceptor.intercept 函数时会传递2个参数 null 和 { handle: originalHandler }
 * 3. 定义一个 logger2Handler 函数 里面包含 logging2Interceptor.intercept (第二个拦截器)函数的执行逻辑
 *   3.1 执行 logging2Interceptor.intercept 函数时会传递2个参数 null 和 { handle: logger1Handler }
 * 
 * 执行逻辑
 * 4. 执行 logger2Handler 函数返回一个可观察对象 ( 此阶段执行所有前置拦截器逻辑 + 路由处理函数 )
 *   4.1 执行 () => logging2Interceptor.intercept(null, { handle: logger1Handler })
 *     4.1.1 执行第二个前置拦截器逻辑后 调用 next.handle()
 *       4.1.1.1 执行第一个前置拦截器逻辑后 调用 next.handle()
 *         4.1.1.1.1 执行路由处理函数逻辑后 返回一个可观察对象
 *       4.1.1.2 调用可观察对象的 pipe 方法传递一个 tap 管道操作符 定义了第一个后置拦截器逻辑
 *     4.1.2 调用可观察对象的 pipe 方法传递一个 tap 管道操作符 定义了第二个后置拦截器逻辑
 * 5. 调用可观察对象的 subscribe 方法 ( 此阶段执行所有后置拦截器逻辑 )
 * 
 * 
 * tap 管道操作符
 *   对上游可观察对象生产发送的值进行副作用处理 ( 不会改变上游可观察对象的值 )
 *     比如日志记录
 */
